package com.bang.study.lru;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

/**
 * @ClassName: SimpleLRUCache
 * @Desc: 基于LinkedHashMap实现的LRU算法
 * @Auther: <Bang>
 * @Date: 2020/08/26 09:07
 * @Version: 1.0
 * @Modified By:
 */
public class SimpleLRUCache<K, V> {

    private final int MAX_CACHE_SIZE;
    private final float DEFAULT_LOAD_FACTORY = 0.75f;

    LinkedHashMap<K, V> map;

    public SimpleLRUCache(int cacheSize) {
        MAX_CACHE_SIZE = cacheSize;
        int capacity = (int)Math.ceil(MAX_CACHE_SIZE / DEFAULT_LOAD_FACTORY) + 1;
        // accessOrder:当参数为true时，按照访问顺序，最近访问的放在头，最老访问的就在尾
        // 当参数为false时，按照插入顺序
        map = new LinkedHashMap<K, V>(capacity, DEFAULT_LOAD_FACTORY, true) {
            private static final long serialVersionUID = 1L;

            // 移除最老的那些元素，可以通过重写这个方法来控制缓存元素的删除，当缓存满了后，就可以通过返回true删除最久未被使用的元素，达到LRU的要求
            @Override
            protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
                // 当map中的数据量大于指定的缓存个数的时候，就自动删除最老的数据
                return size() > MAX_CACHE_SIZE;
            }
        };
    }

    public synchronized void put(K key, V value) {
        map.put(key, value);
    }
    public synchronized V get(K key) {
        return map.get(key);
    }
    public synchronized void remove(K key) {
        map.remove(key);
    }
    public synchronized Set<Map.Entry<K, V>> getAll() {
        return map.entrySet();
    }
    @Override
    public String toString() {
        StringBuilder stringBuilder = new StringBuilder();
        for (Map.Entry<K, V> entry : map.entrySet()) {
            stringBuilder.append(String.format("%s: %s  ", entry.getKey(), entry.getValue()));
        }
        return stringBuilder.toString();
    }

    public static void main(String[] args) {
        SimpleLRUCache<String, String> lru = new SimpleLRUCache<>(5);
        lru.put("球员1", "杜兰特");
        lru.put("球员2", "表妹");
        lru.put("球员3", "库里");
        System.out.println(lru);
        lru.get("球员1");
        System.out.println(lru);
        lru.put("球员4", "一哥");
        lru.put("球员5", "汤姆");
        System.out.println(lru);
        lru.put("球员6", "格林");
        System.out.println(lru);

        LinkedHashMap<Object, Object> linkedHashMap = new LinkedHashMap<Object, Object>(1, 1, true);
    }



}
